package com.dymall.item.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dymall.common.domain.PageDTO;
import com.dymall.common.utils.BeanUtils;
import com.dymall.item.domain.dto.ItemDTO;
import com.dymall.item.domain.po.Item;
import com.dymall.item.domain.po.ItemDoc;
import com.dymall.item.domain.query.ItemPageQuery;
import com.dymall.item.service.ItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {
    private final ItemService itemService;

    private RestHighLevelClient client;

    /**
     * 模糊查询搜索
     * @param itemPageQuery
     * @return
     */
//    @ApiOperation("搜索商品")
//    @GetMapping("/list")
//    public PageDTO<ItemDTO> search(ItemPageQuery itemPageQuery){
//        Page<Item> result = itemService.lambdaQuery().like(StrUtil.isNotBlank(itemPageQuery.getKey()), Item::getName, itemPageQuery.getKey())
//                .eq(StrUtil.isNotBlank(itemPageQuery.getBrand()), Item::getBrand, itemPageQuery.getBrand())
//                .eq(StrUtil.isNotBlank(itemPageQuery.getCategory()), Item::getCategory, itemPageQuery.getCategory())
//                .between(itemPageQuery.getMaxPrice() != null, Item::getPrice, itemPageQuery.getMinPrice(), itemPageQuery.getMaxPrice())
//                .page(itemPageQuery.toMpPage("update_time", false));//默认按更新时间排序，倒序
//        return PageDTO.of(result, ItemDTO.class);//使用自定义的PageDTO的静态方法，将元素类型转为ItemDTO并封装到PageDTO中
//    }

    /**
     * Elasticsearch 组件查询，优化查询性能200ms -> 100ms
     * @param itemPageQuery
     * @return
     */
    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO<ItemDTO> search(ItemPageQuery itemPageQuery) throws IOException {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.113.131:9200")
        ));

        int pageNo = 1, pageSize = 500;
        //1.准备Request对象
        SearchRequest request = new SearchRequest("items");
        //2.组织DSL参数
        //2.1.query参数
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        boolean flag = false;
        if(StrUtil.isNotBlank(itemPageQuery.getKey())){
            builder.must(QueryBuilders.matchQuery("name", itemPageQuery.getKey()));
            flag = true;
        }
        if(StrUtil.isNotBlank(itemPageQuery.getBrand())){
            builder.filter(QueryBuilders.termQuery("brand", itemPageQuery.getBrand()));
            flag = true;
        }
        if(StrUtil.isNotBlank(itemPageQuery.getCategory())){
            builder.filter(QueryBuilders.termQuery("category", itemPageQuery.getCategory()));
            flag = true;
        }
        if(itemPageQuery.getMaxPrice() != null){
            builder.filter(QueryBuilders.rangeQuery("price").gte(itemPageQuery.getMinPrice()).lte(itemPageQuery.getMaxPrice()));
            flag = true;
        }
        if(!flag){
            request.source().query(QueryBuilders.matchAllQuery());
        }
        else{
            request.source().query(builder);
        }
        //2.2.分页
        request.source().from((pageNo - 1)*pageSize).size(pageSize);
        //2.3.排序
        request.source()
                .sort("sold", SortOrder.DESC)
                .sort("price", SortOrder.ASC);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        SearchHits searchHits = response.getHits();
        //4.1.总条数
        long total = searchHits.getTotalHits().value;
        //4.2.命中的数据
        SearchHit[] hits = searchHits.getHits();
        List<ItemDoc> docs = new ArrayList<>();
        for(SearchHit hit : hits){
            //获取source结果
            String json = hit.getSourceAsString();
            //转为ItemDoc
            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
            docs.add(doc);
        }

        if(client != null){
            client.close();
        }

        return new PageDTO<ItemDTO>((long)pageNo*pageSize, (long)pageSize, BeanUtils.copyList(docs, ItemDTO.class));
    }

    /**
     * 解析结果
     * @param response
     */
    private static void parseResponseResult(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        //4.1.总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("total = " + total);
        //4.2.命中的数据
        SearchHit[] hits = searchHits.getHits();
        for(SearchHit hit : hits){
            //获取source结果
            String json = hit.getSourceAsString();
            //转为ItemDoc
            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
        }
    }
}
